package net.butfly.bus.client.config;

import java.io.InputStream;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;

import net.butfly.albacore.exception.SystemException;
import net.butfly.bus.Constants;
import net.butfly.bus.client.connection.ConnectionFactory;
import net.butfly.bus.config.bean.ConnectionBean;
import net.butfly.bus.config.bean.NodeBean;
import net.butfly.bus.config.detail.ConnectionConfig;
import net.butfly.bus.config.parser.XMLConfigParser;
import net.butfly.bus.impl.Connection;

import org.dom4j.Element;

public class XMLConfigClientParser extends XMLConfigParser {
	public XMLConfigClientParser(InputStream source) {
		super(source);
	}

	@SuppressWarnings("unchecked")
	@Override
	public ClientConfig parse() {
		ClientConfig config = new ClientConfig();
		super.parse(config);
		config.setNodesMap(this.parseNodes("node"));
		return config;
	}

	@Override
	protected NodeBean createNodeBean(String nodeId, Element nodeEle) {
		ConnectionBean connectionBean = parseConnection(nodeId, nodeEle);
		return new NodeBean(nodeId, nodeEle.attributeValue("txMatching"), connectionBean, null, null);
	};

	private ConnectionBean parseConnection(String nodeId, Element nodeEle) {
		String id = nodeEle.attributeValue("connection");
		Element element;
		if (id != null) {
			element = (Element) this.root.selectSingleNode("connection[@id='" + id + "']");
			if (element == null) {
				throw new SystemException(Constants.UserError.NODE_CONNECTION_NOT_FOUND, "没有找到 id为\"" + nodeId
						+ "\"的 node 所配置的 id为 \"" + id + "\" 的 connection");
			}
		} else {
			element = (Element) nodeEle.selectSingleNode("connection");
			if (element == null) {
				throw new SystemException(Constants.UserError.NODE_CONNECTION_NOT_FOUND, "id为\"" + nodeId
						+ "\"的 node 没有配置 connection");
			}
		}
		String type = element.attributeValue("type");
		if (type == null) {
			throw new SystemException(Constants.UserError.NODE_CONNECTION_NOT_FOUND, "id为 \"" + id
					+ "\" 的 connection 没有配置 type 属性");
		}
		logger.info("节点(Id:" + nodeId + ")对应Connection:\n	" + element.asXML());
		Class<? extends Connection> clazz = classForName(type);
		ConnectionConfig config = ConnectionFactory.getConfig(clazz);

		if (config == null) {
			throw new SystemException(Constants.UserError.NODE_CONNECTION_NOT_FOUND,
					"can not found connection type with name \"" + type + "\" on nodes loading");
		}
		try {
			processConfigObj(config, element);
		} catch (Exception ex) {
			throw new SystemException(Constants.UserError.NODE_CONNECTION_NOT_FOUND, "设置id为 " + id + " 的 join 参数出错",
					ex);
		}
		return new ConnectionBean(id, clazz, config);
	}

	@SuppressWarnings("unchecked")
	private static void processConfigObj(ConnectionConfig configObject, Element element) throws IllegalArgumentException,
			IllegalAccessException {
		Class<?> clz = configObject.getClass();
		while (!clz.equals(Object.class)) {
			Field[] fAry = clz.getDeclaredFields();
			if (fAry != null) {
				for (Field f : fAry) {
					Object v = null;
					if (List.class.isAssignableFrom(f.getType())) {
						List<Element> eleList = element.selectNodes(f.getName());
						if (eleList != null) {
							List<String> itemList = new ArrayList<String>();
							for (Element ele : eleList) {
								String ts = ele.getTextTrim();
								if (!("".equals(ts))) {
									itemList.add(ts);
								}
							}
							v = itemList;
						}
					} else {
						Element ele = (Element) element.selectSingleNode(f.getName());
						if (ele != null) {
							String ts = ele.getTextTrim();
							if (!("".equals(ts))) {
								v = ts;
							}
						}
					}
					if (v != null) {
						boolean af = f.isAccessible();
						f.setAccessible(true);
						f.set(configObject, v);
						f.setAccessible(af);
					}
				}
			}
			clz = clz.getSuperclass();
		}
	}
}
